<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------

// 应用公共文件
use think\facade\Validate;

/**
 * 用 PHP 计算样本 皮乐逊相关系数
 * @param $x
 * @param $y
 * @url https://yhhuang1966.blogspot.com/2013/08/php_4.html
 * @return float|int
 * @author hongwei 2019-03-25 整理并翻译为简体中文
 * @example
 * $x = [25, 23, 27, 35, 30];
 * $y = [35, 27, 36, 45, 42];
 * $corr 返回结果：0.94137554144354
 */
function correlationAnalysis($x, $y)
{
    // $x       = [25, 23, 27, 35, 30];
    // $y       = [35, 27, 36, 45, 42];
    $xAvg       = array_sum($x) / count($x);  //X 平均值
    $yAvg       = array_sum($y) / count($y);  //Y 平均值
    $xSum       = array_sum($x);              //X 总和
    $ySum       = array_sum($y);              //Y 总和
    $xSquareSum = 0;                          //X 平方和累计
    $ySquareSum = 0;                          //Y 平方和累计
    $xMd        = [];                         //X 离均差
    $yMd        = [];                         //Y 离均差
    $mdDrossSum = 0;                          //X,Y 离均差交乘积和
    $count      = count($x);                  //元素個數
    //$xDifSquareSum = '';
    for ($i = 0; $i < $count; ++$i) {
        $xDif       = (float)$x[$i] - $xAvg;  //X 离均差
        $yDif       = (float)$y[$i] - $yAvg;  //Y 离均差
        $xMd[$i]    = $xDif;
        $yMd[$i]    = $yDif;
        $mdDrossSum += $xDif * $yDif;         //X,Y 离均差交乘积和
        //$xDifSquareSum += pow($xDif, 2);    //X 离均差平方和
        $xSquareSum += pow($x[$i], 2);  //X 平方和累计
        $ySquareSum += pow($y[$i], 2);  //Y 平方和累计
    } //end of for
    //计算样本标准差 & 乘积
    $xStd  = sqrt(($xSquareSum - pow($xSum, 2) / $count) / ($count - 1));
    $yStd  = sqrt(($ySquareSum - pow($ySum, 2) / $count) / ($count - 1));
    $xyStd = $xStd * $yStd; //兩标准差乘积
    //计算样本共变异数
    $covariance = $mdDrossSum / ($count - 1);
    //计算相关系数
    $corr = $covariance / $xyStd;
    return $corr;
}

/**
 * Notes :处理gis站点数据四舍五入
 * @param $stationArr
 * @param $param
 * @return array
 * @author lichao   2019/6/13
 */
function roundStationData($stationArr, $param)
{
    $station = array();
    foreach ($stationArr as $key => &$value) {
        if ($value === '-') {
            $station[$key] = '';
            continue;
        }
        if ($param == 'co') {
            $station[$key] = round($value, 1);
        } else {
            $station[$key] = round($value);
        }
    }
    
    return $station;
}

/**
 * Notes :处理gis站点日期格式
 * @param $timeArr
 * @return array
 * @author lichao   2019/6/12
 */
function handleStationTime($timeArr)
{
    $stationTime = array();
    foreach ($timeArr as $key => $value) {
        $stationTime[$key] = date("Y-m-d H:i:s", strtotime($value));
    }
    
    return $stationTime;
}

/**
 * Notes :管控时间，计算日期段时间（勿修改！！！）
 * @param $startDate
 * @param $endDate
 * @param bool $hour
 * @return array
 * @author lichao   2019/6/25
 */
function getDateFromRange($startDate, $endDate, $hour = false)
{
    $startTimestamp = strtotime($startDate);
    $endTimestamp   = strtotime($endDate);
    // 计算日期段内有多少天
    if ($hour) {
        $days = ($endTimestamp - $startTimestamp) / 3600;
        // 保存每天日期
        $date = array();
        for ($i = 0; $i < $days; $i++) {
            $date[] = date('Y-m-d H:i', $startTimestamp + (3600 * $i));
        }
    } else {
        $days = ($endTimestamp - $startTimestamp) / 86400;
        // 保存每天日期
        $date = array();
        for ($i = 0; $i < $days; $i++) {
            $date[] = date('Y-m-d 00:00:00', $startTimestamp + (86400 * $i));
        }
    }
    
    return $date;
}

/**
 * 二维数组用某个二维元素的值作为一维元素的键
 * 常用于数据库结果用某个字段作为记录的索引键
 * @param array $array 输入数组
 * @param string $field 要作为键的字段名
 * @param bool $unique 要做键的字段是否唯一(该字段与记录是否一一对应)
 * @return    array
 * @author    Baiyu    2017-01-23
 */
function field_as_key($array, $field, $unique = FALSE)
{
    $result = array();
    
    foreach ($array as $item) {
        if (isset($item[$field])) {
            if (!$unique && isset($result[$item[$field]])) {
                $unique                  = TRUE;
                $result[$item[$field]]   = array($result[$item[$field]]);
                $result[$item[$field]][] = $item;
            } elseif ($unique) {
                $result[$item[$field]][] = $item;
            } else {
                $result[$item[$field]] = $item;
            }
        }
    }
    return $result;
}

/**
 * 抛出异常的方式
 * @param $msg
 * @author hongwei 2019-07-01
 */
//function exception($msg)
//{
//    die($msg);
//}

/**
 * 将对象转化为数组
 * @param $obj
 * @param bool $idMulti
 * @return array
 * @author hongwei 2019-07-04
 */
function mongoObjToArray($obj)
{
    $newData = [];
    foreach ($obj as $key => $value) {
        foreach ($value as $k => $v) {
            $newData[$key][$k] = $v;
        }
    }
    return $newData;
}

/**
 * Groups an array by a given key. Any additional keys will be used for grouping
 * THE NEXT SET OF SUB-ARRAYS.
 *
 * @param array $arr The array to be grouped.
 * @param mixed $key,... A set of keys to group by.
 *
 * @return array
 * @author Jake Zatecky
 *
 */
function array_group_by(array $arr, $key): array
{
    if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) {
        trigger_error('array_group_by(): The key should be a string, an integer, a float, or a function', E_USER_ERROR);
    }
    $isFunction = !is_string($key) && is_callable($key);
    // Load the new array, splitting by the target key
    $grouped = [];
    foreach ($arr as $value) {
        $groupKey = null;
        if ($isFunction) {
            $groupKey = $key($value);
        } else if (is_object($value)) {
            $groupKey = $value->{$key};
        } else {
            $groupKey = $value[$key];
        }
        $grouped[$groupKey][] = $value;
    }
    // Recursively build a nested grouping if more parameters are supplied
    // Each grouped array value is grouped according to the next sequential key
    if (func_num_args() > 2) {
        $args = func_get_args();
        foreach ($grouped as $groupKey => $value) {
            $params = array_merge([$value], array_slice($args, 2, func_num_args()));
            // $grouped[$groupKey] = call_user_func_array(array($this, "array_group_by"), $params);
        }
    }
    return $grouped;
}

/**
 * Notes :发起http POST请求
 * @param      $url
 * @param null $data
 * @param bool $json
 * @return array|mixed
 * @author lichao   2019/5/29
 */
function curl_request($url, $data = NULL, $json = false)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);                     // 设置url
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);  // 验证
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);  // 证书验证
    if (!empty($data)) {
        if ($json && is_array($data)) {
            $data = json_encode($data);
        }
        curl_setopt($curl, CURLOPT_POST, 1);            // POST请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);         // 发送数据
        if ($json) {            // 发送JSON数据
            curl_setopt($curl, CURLOPT_HEADER, 0);      // 设置头文件的信息作为数据流输出
            curl_setopt($curl, CURLOPT_HTTPHEADER,
                array(
                    'Content-Type: application/json; charset=utf-8'
                )
            );
        }
    }
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);      // 设置获取的信息以文件流的形式返回，而不是直接输出
    $res     = curl_exec($curl);    // 执行命令
    $errorno = curl_errno($curl);   // 返回错误
    if ($errorno) {
        return array('errorno' => false, 'errmsg' => $errorno);
    }
    curl_close($curl);              // 关闭URL请求
    return json_decode($res, true);
}


/**
 * @return string
 * @author ayy 2019/07/11
 */
function get_week()
{
    switch (date('w')) {
        case '1':
            $week = '周一';
            break;
        case '2':
            $week = '周二';
            break;
        case '3':
            $week = '周三';
            break;
        case '4':
            $week = '周四';
            break;
        case '5':
            $week = '周五';
            break;
        case '6':
            $week = '周六';
            break;
        case '0':
            $week = '周日';
            break;
        default :
            $week = '';
    }
    return $week;
}

function V(array $rule, array $rename = [], array $data = null, array $message = [])
{
    if ($data === null) {
        $data = input();
    }
    $rule0    = array_filter($rule);
    $validate = validate::make($rule0);
    $validate->message($message);
    if (!$validate->check($data)) {
        $data = [
            'code' => 101,
            'msg' => $validate->getError(),
        ];
        return $data;
    } else {
        $result = [];
        foreach ($rule as $k => $v) {
            $k = explode('|', $k)[0];//兼容"|"
            if (isset($rename[$k])) {
                $result[$rename[$k]] = input($k);
            } else {
                $result[$k] = input($k);
            }
        }
        return $result;
    }
}

/**
 * curl 模拟get请求
 * @param string $url   请求地址
 * @param int $timeout  超时时间(秒)
 * @return mixed
 */
function get($url, $timeout = 3)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); // 设置超时
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

/**
 * 数值非四舍五入保留两位小数
 * @author hongwei 2019-07-26
 * @param float $num 数值
 * @param int $scale 保留位数
 * @return mixed|string
 */
function getNum($num, $scale = 2) {
    $numStr = (string)$num . str_repeat('0', $scale);

    //匹配精度前的数值
    if(preg_match('#^\d+\.\d{0,'.$scale.'}#', $numStr, $match)) {
        return $match[0];
    } else {
        return '0';
    }
}
